home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-07-21 | 9.6 KB | 411 lines | [TEXT/CWIE] |
- // Sound Object Handler for the WASTE Text Engine
- // by Michael F. Kamprath, kamprath@kagi.com
- // maintenance by John C. Daub, hsoi@eden.com
- //
- // v1.0, 16 March 1995
- // v1.0.1, 13 May 1995, changed the sound playing code a little. Also added gestalt
- // check for sound recording device when CreateNewSoundObject()
- // is called.
- // v1.1, 5 June 95, Made some changes recomended by Chris Thomas, <THUNDERONE@delphi.com>:
- // - Playing an object's sound is done by ultilizing the object's data
- // directly rather than making a copy. Using PlaySoundHandle() for
- // your sounds still makes a copy.
- // - Added the public routines StopCurrentSound() and IsSoundPlaying().
- // - Option to have the sound sound created at the handler's initilization.
- // - Added InstallSoundObject() to install sound object handler only.
- //
- // v1.2, 28 March 1996. Bug fixes by John C. Daub <mailto:hsoi@eden.com>
- // - Removed a not operator from SoundIsPlaying() so the function works correctly
- // - Adjusted CheckSoundStatus() to work with the fixed SoundIsPlaying()
- // - Minor updates: more precompiler directives, WASTE 1.2a5 compatability
- //
- // v1.2.2, 16 July 1996. Added compatability with WASTE 1.2 and CW9
- // Restructured installation routines
- //
- // v1.2.4, 16 January 1997. Removed the declaration of CreateNewSoundChannel()
- // from WE_snd_Handler.h. If this file was compiled with "Activate
- // C++ Compiler" turned on (then compiling this C file as C++), there
- // would be an error of inconsistent linkage because an 'extern'
- // object was then getting redeclared as 'static'. Hopefully this won't
- // cause any problems for people.
- //
- // v1.2.5, 25 April 1997. Added a gCurrentSound != nil check in CheckSoundStatus() just to be safe
- //
-
- #ifndef _WASTE_
- #include "WASTE.h"
- #endif
-
- #ifndef __GESTALT__
- #include <Gestalt.h>
- #endif
-
- #include "WE_snd_Handler.h"
- #ifndef _WASTEOBJECTS_
- #include "WASTE_Objects.h"
- #endif
-
- #ifndef true
- #define true 1
- #endif
-
- #ifndef false
- #define false 0
- #endif
-
- //
- // Local only routines
- //
-
- static OSErr PlayCurrentGlobalSound( void );
- static SndChannelPtr CreateNewSoundChannel( void );
-
- //
- // Sound Channel and current playing sound pointers
- //
- static SndChannelPtr gSoundChannel = nil;
- static SndListHandle gCurrentSound = nil;
- static short gCurSoundHandleStatus = 0;
-
- #define kIsWASTESound 0x0100
-
-
-
- void InitSoundObjectHandler( void )
- {
- #if CREATE_CHANNEL_AT_INIT
- gSoundChannel = CreateNewSoundChannel();
- #endif
- }
-
-
- OSErr InstallSoundObject( WEReference theWE )
- {
- OSErr iErr;
-
- #ifdef __cplusplus
- static WENewObjectUPP newSndUPP = NewWENewObjectProc(HandleNewSound);
- static WEDisposeObjectUPP disposeSndUPP = NewWEDisposeObjectProc(HandleDisposeSound);
- static WEDrawObjectUPP drawSndUPP = NewWEDrawObjectProc(HandleDrawSound);
- static WEClickObjectUPP clickSndUPP = NewWEClickObjectProc(HandleClickSound);
- #else
- static WENewObjectUPP newSndUPP = NULL;
- static WEDisposeObjectUPP disposeSndUPP = NULL;
- static WEDrawObjectUPP drawSndUPP = NULL;
- static WEClickObjectUPP clickSndUPP = NULL;
-
- if ( newSndUPP == NULL )
- newSndUPP = NewWENewObjectProc(HandleNewSound);
- if ( disposeSndUPP == NULL )
- disposeSndUPP = NewWEDisposeObjectProc(HandleDisposeSound);
- if ( drawSndUPP == NULL )
- drawSndUPP = NewWEDrawObjectProc(HandleDrawSound);
- if ( clickSndUPP == NULL )
- clickSndUPP = NewWEClickObjectProc(HandleClickSound);
- #endif
-
- if ( newSndUPP != NULL )
- iErr = WEInstallObjectHandler(kTypeSound, weNewHandler, (UniversalProcPtr)newSndUPP, theWE);
- else
- iErr = weUnknownObjectTypeErr;
- if (iErr) return(iErr);
-
- if ( disposeSndUPP != NULL )
- iErr = WEInstallObjectHandler(kTypeSound, weDisposeHandler, (UniversalProcPtr)disposeSndUPP, theWE);
- else
- iErr = weUnknownObjectTypeErr;
- if (iErr) return(iErr);
-
- if ( drawSndUPP != NULL )
- iErr = WEInstallObjectHandler(kTypeSound, weDrawHandler, (UniversalProcPtr)drawSndUPP, theWE);
- else
- iErr = weUnknownObjectTypeErr;
- if (iErr) return(iErr);
-
- if ( clickSndUPP != NULL )
- iErr = WEInstallObjectHandler(kTypeSound, weClickHandler, (UniversalProcPtr)clickSndUPP, theWE);
- else
- iErr = weUnknownObjectTypeErr;
- if (iErr) return(iErr);
-
- return(noErr);
- }
-
- //
- // New Object Handler for sounds
- //
- pascal OSErr HandleNewSound(Point *defaultObjectSize,WEObjectReference objectRef)
- {
- #pragma unused (objectRef)
-
- (*defaultObjectSize).h = 32;
- (*defaultObjectSize).v = 32;
-
- return(noErr);
- }
- //
- // Dispose Object handler for sounds
- //
-
- pascal OSErr HandleDisposeSound(WEObjectReference objectRef )
- {
- SndListHandle theSound;
-
- theSound = (SndListHandle)WEGetObjectDataHandle(objectRef);
-
- if (theSound == gCurrentSound)
- StopCurrentSound();
-
- DisposeHandle((Handle)theSound);
-
- return(MemError());
- }
- //
- // Draw Object handler for sounds
- //
- pascal OSErr HandleDrawSound(Rect *destRect, WEObjectReference objectRef )
- {
- #pragma unused (objectRef)
-
- OSErr iErr;
-
- iErr = PlotIconID(destRect,atNone,ttNone,kSoundIconID);
-
- return( iErr );
- }
- //
- // Click Object Handler for sounds
- //
-
- pascal Boolean HandleClickSound( Point hitPt,
- short modifiers,
- long clickTime,
- WEObjectReference objectRef)
- {
- #pragma unused ( hitPt, clickTime)
-
- OSErr iErr;
-
- if (modifiers & 0x0001) // look for double-clicks
- {
- iErr = StopCurrentSound();
-
- gCurrentSound = (SndListHandle)WEGetObjectDataHandle( objectRef );
- iErr = PlayCurrentGlobalSound();
- gCurSoundHandleStatus += kIsWASTESound;
-
- if (!iErr)
- return(true);
- else
- {
- StopCurrentSound();
- return(false);
- }
- }
- else
- return(false);
-
- }
-
- //
- // PlaySelectedSound()
- // If a sound object, and only a sound object, is selected,
- // PlaySelectedSound() will play it.
- //
- OSErr PlaySelectedSound( WEReference theWE )
- {
- WEObjectReference objectRef;
- SndListHandle theSound;
- OSErr iErr = noErr;
-
- iErr = WEGetSelectedObject( &objectRef, theWE );
- if (!iErr)
- {
- theSound = (SndListHandle)WEGetObjectDataHandle( objectRef );
- iErr = PlaySoundHandle( theSound );
- }
-
- return( iErr );
- }
- //
- // CreateNewSoundObject()
- // Uses built in sound recording to create a new sound object.
- //
- OSErr CreateNewSoundObject( WEReference theWE )
- {
- OSErr iErr;
- SndListHandle sndHandle = nil;
- long gestaltResponse;
- Point corner = {32,32};
-
- iErr = Gestalt(gestaltSoundAttr, &gestaltResponse);
- if ( (iErr == noErr)&&(gestaltResponse&gestaltHasSoundInputDevice))
- {
- iErr = SndRecord(nil,corner,siGoodQuality,&sndHandle);
-
- if (iErr == noErr)
- {
- corner.h = 32;
- corner.v = 32;
- WEInsertObject( kTypeSound, (Handle)sndHandle, corner, theWE );
- }
- }
- return( iErr );
- }
-
- //
- // PlaySoundHandle()
- // Ultility routine to play a sound async. Maintains a sound channel
- // and the sound data to do so.
- //
- // Intended for use by external code.
- //
-
- OSErr PlaySoundHandle( SndListHandle theSound )
- {
- OSErr iErr = noErr;
-
-
- // If a sound is currently playing, stop it and dispose of it's buffer.
- iErr = StopCurrentSound();
-
- // create a new buffer for the selected sound.
- gCurrentSound = theSound;
- iErr = HandToHand((Handle *)&(gCurrentSound));
-
- if (!iErr)
- {
- iErr = PlayCurrentGlobalSound();
-
- if (iErr)
- {
- // FYI, HLock is called in PlayCurrentGlobalSound()
- HUnlock( (Handle)gCurrentSound );
- DisposeHandle( (Handle)gCurrentSound );
- gCurrentSound = nil;
- }
- }
-
- return(iErr);
- }
-
- //
- // PlayCurrentGlobalSound()
- // Used locally by the object handler to play the current sound.
- //
-
- static OSErr PlayCurrentGlobalSound( void )
- {
- OSErr iErr = noErr;
-
- // check for sound channel
- if (!gSoundChannel)
- gSoundChannel = CreateNewSoundChannel();
-
- if (gCurrentSound&&gSoundChannel)
- {
- // Lock the buffer and play the sound.
- gCurSoundHandleStatus = HGetState( (Handle)gCurrentSound );
- HLockHi( (Handle)gCurrentSound );
- // FYI, gCurrentSound is unlocked and disposed of upon return to
- // PlaySoundHandle()
-
- iErr = SndPlay(gSoundChannel,gCurrentSound,true);
- }
-
- return(iErr);
- }
-
- //
- // StopCurrentSound()
- // Stops the current sound and returns memory to original state.
- //
-
- OSErr StopCurrentSound( void )
- {
- SndCommand cmd;
- OSErr iErr;
-
- if (gCurrentSound&&gSoundChannel)
- {
- cmd.cmd = quietCmd;
- iErr = SndDoImmediate(gSoundChannel,&cmd);
-
- HSetState( (Handle)gCurrentSound, (char)(gCurSoundHandleStatus&0x00FF) );
-
- iErr = MemError();
- if (iErr) return(iErr);
-
- if (!(gCurSoundHandleStatus&kIsWASTESound))
- DisposeHandle( (Handle)gCurrentSound );
-
- gCurrentSound = nil;
- gCurSoundHandleStatus = 0;
-
- return(MemError());
- }
-
- return(noErr);
- }
- //
- // CreateNewSoundChannel()
- // Used to create a new shound channel.
- //
- static SndChannelPtr CreateNewSoundChannel( void )
- {
- OSErr iErr;
- SndChannelPtr chan;
-
- // allocate a sound channel
- chan = (SndChannelPtr)NewPtrClear(sizeof(SndChannel));
- if ( chan != nil )
- {
- chan->qLength = stdQLength; //128 sound commands
- iErr = SndNewChannel(&chan, sampledSynth, 0, nil);
- if (iErr)
- {
- DisposePtr((Ptr)chan);
- chan = nil;
- }
- }
- return(chan); // return SndChannelPtr
- }
-
- //
- // CheckSoundStatus()
- // Should be called periodically to dispose of unneeded sound buffers.
- //
- void CheckSoundStatus( void )
- {
- if ((!SoundIsPlaying()) && (gCurrentSound !=nil))
- {
- HSetState( (Handle)gCurrentSound, (char)(gCurSoundHandleStatus&0x00FF) );
-
- if (!gCurSoundHandleStatus&kIsWASTESound)
- DisposeHandle( (Handle)gCurrentSound );
-
- gCurrentSound = nil;
- gCurSoundHandleStatus = 0;
- }
- }
-
- //
- // SoundIsPlaying()
- // Returns true if a sound is being played by the object handler,
- // false if not.
- //
-
- Boolean SoundIsPlaying( void )
- {
- OSErr iErr;
- SCStatus theStatus;
-
- if (gSoundChannel)
- {
- iErr = SndChannelStatus(gSoundChannel,sizeof(SCStatus),&theStatus);
- if (( theStatus.scChannelBusy )&&(gCurrentSound))
- return( true );
- }
-
- return( false );
- }